home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 12 / BBS in a box XII-2.iso / Files II / Prog / M / MacWT 0.04.sit / Mac WT source / turlsLibs / DirScrnWrite.c / DirScrnWrite.c
Encoding:
Text File  |  1994-05-10  |  11.1 KB  |  481 lines  |  [TEXT/MMCC]

  1. //==================================================================
  2. // DirScrnWrite.c                                    <tur xx-xx-92>
  3. //
  4. //    Direct Screen Write Routines, hacked from my other bitz...
  5. //
  6. //    Comments, Bug Reports/Fixes, etc, to turly@isltd.insignia.com
  7. //
  8. //==================================================================
  9.  
  10. #ifndef    __QUICKDRAW__
  11. #include "LoadMacHeaders.h"
  12. #endif    /* __QUICKDRAW__ */
  13.  
  14. #include "RectUtils.h"
  15. #include "DirScrnWrite.h"
  16. #include "Failure.h"
  17.  
  18.  
  19. // 
  20.  
  21. /* Want to find out if a GDevice is actually being used? Use this: */
  22.  
  23. #define    kScrnDevMask            ((1 << screenDevice) | (1 << screenActive))
  24. #define    IsActiveScreen(gdh)        (((*gdh)->gdFlags & kScrnDevMask) == kScrnDevMask)
  25.  
  26. #define    kRGBTOLERANCE            0x2000
  27.  
  28.  
  29. // Nasty lowmem globals...
  30.  
  31. #define    GetDeviceList()            (*(GDHandle *)0x08A8)
  32. #define    GetCrsrVis()            (*(char *)0x08CC)
  33. #define    GetMMU32Bit()            (*(char *)0x0CB2)
  34. #ifndef    GetMBarHeight
  35. #define GetMBarHeight()            (*(short*)0x0BAA)
  36. #endif
  37. #define    GetMainDevice()            (*(GDHandle *)0x08A4)
  38.  
  39.  
  40. /***********************************************************************************/
  41.  
  42. long            *ReplicatedByteLUT;
  43. int                gPaletteColorsUsed;
  44. CTabHandle        gDirClut;
  45. PaletteHandle    gDirPalette;
  46. GDHandle        gTheScreenDevice;
  47.  
  48. const Point        nullPt = {0, 0};
  49.  
  50.  
  51. /**/
  52.  
  53.  
  54. static Rect    *cursorShieldRect;
  55. static char    gOriginally32Bit, gPreviouslyVisible;
  56. static Rect gGlobalWinRect;
  57. static unsigned long gMacRowBytes;
  58. static unsigned long gMacScreenPtr, gWinScreenPtr;
  59. static RgnHandle    gPreviousVisRgn, gBoundRgn;
  60. static int            gDirScrnInited = 0,
  61.                     gDirScrnWindowInited = 0;
  62.  
  63. /**/
  64.  
  65.  
  66. /* BeginDirectScreenWrite
  67. **    The rectangle into which you're writing, if passed, should be in GLOBAL COORDINATES.
  68. **    We may need to get the system into 32-bit mode when writing to the screen...
  69. */
  70. void BeginDirectScreenWrite(Rect *globalRect)
  71. {
  72.     if ((cursorShieldRect = globalRect) != nil)
  73.         ShieldCursor(globalRect, nullPt);
  74.  
  75.     gOriginally32Bit = GetMMU32Bit();
  76.  
  77.     if (gOriginally32Bit == false32b) {
  78.         char    b32 = true32b;
  79.  
  80.         SwapMMUMode(&b32);
  81.     }
  82. }
  83.  
  84.  
  85. /**/
  86.  
  87.  
  88. void EndDirectScreenWrite(void)
  89. {
  90.     if (!gOriginally32Bit) {
  91.         char    b24 = false32b;
  92.  
  93.         SwapMMUMode(&b24);
  94.     }
  95.  
  96.     if (cursorShieldRect)
  97.         ShowCursor();
  98. }
  99.  
  100.  
  101. /**/
  102.  
  103.  
  104. // If wp is completely visible, returns its business Rect in "gGlobalWinRect."
  105.  
  106. static Boolean GetVisibleRect(WindowPtr wp)        // return true if completely visible
  107. {
  108.     Rect        *boundP;
  109.     Rect        locRect, globRect;
  110.     GrafPtr        oldPort;
  111.     
  112.     GetPort(&oldPort);
  113.     SetPort(wp);
  114.  
  115.     locRect = wp->portRect;
  116.  
  117.     // get the window’s rect in global coords
  118.     globRect = locRect;
  119.  
  120.     LocalToGlobal((Point *)&globRect);
  121.     LocalToGlobal(&((Point *)&globRect)[1]);
  122.  
  123.     // The visrgns could be the same if the window was moved onscreen but is still
  124.     // "equally" visible after the move...  (Recall: visRgns are in LOCAL coords!)
  125.  
  126.     if (!EqualRect(&globRect, &gGlobalWinRect) || !EqualRgn(gPreviousVisRgn, wp->visRgn)) {
  127.  
  128.         CopyRgn(wp->visRgn, gPreviousVisRgn);    // Copy it...
  129.  
  130.         gPreviouslyVisible = false;                // Assume that the window is obscured until proven otherwise
  131.  
  132.         gGlobalWinRect = globRect;                // copy rectangles
  133.  
  134.         RectRgn(gBoundRgn, &locRect);            // "locRect" -- local coords
  135.         SectRgn(gBoundRgn, gPreviousVisRgn, gBoundRgn);
  136.  
  137.         // The result of this intersection must be a rectangle with no holes;
  138.         // i.e., the window must be completely visible.
  139.  
  140.         if ((*gBoundRgn)->rgnSize == 10) {            // size of a "pure" rectangular region
  141.             boundP = &(*wp->visRgn)->rgnBBox;
  142.     
  143.             if (RectInRect(&locRect, boundP)) {        // locRect completely inside the bounds rect
  144.                 gPreviouslyVisible = true;
  145.             }
  146.         }
  147.     }
  148.  
  149.     SetPort(oldPort);
  150.  
  151.     return gPreviouslyVisible;
  152. }
  153.  
  154.  
  155. /**/
  156.  
  157. // CanWriteDirectToScreen -- return true if we can write directly onscreen to the entire "win".
  158.  
  159. Boolean CanWriteDirectToScreen(WindowPtr win)
  160. {
  161.     GDHandle    gdh;
  162.     Rect        *gdRP;
  163.  
  164.     FailNil(win);
  165.  
  166.     if (GetVisibleRect(win)) {        // Window must be completely visible
  167.  
  168.         // Search thru all devices for this Rect
  169.  
  170.         gdh = GetDeviceList();
  171.         while (gdh != 0) {
  172.             gdRP = &(*gdh)->gdRect;
  173.             if (RectInRect(&gGlobalWinRect, gdRP)) {
  174.  
  175.                 // We may be able to write directly to the screen...
  176.  
  177.                 if (IsActiveScreen(gdh)) {
  178.                     PixMapHandle    pmh;
  179.  
  180.                     pmh = (*gdh)->gdPMap;
  181.                     if ((*pmh)->pixelType == clutType && (*pmh)->pixelSize == 8) {
  182.                         gMacRowBytes = (*pmh)->rowBytes & 0x3fff;
  183.                         gMacScreenPtr = (unsigned long)(*pmh)->baseAddr;
  184.                         gWinScreenPtr = gMacScreenPtr + 
  185.                                 ((gGlobalWinRect.top - gdRP->top) * gMacRowBytes) + gGlobalWinRect.left - gdRP->left;
  186.                         gTheScreenDevice = gdh;
  187.                         return true;
  188.                     }
  189.                 }
  190.             }
  191.             gdh = (GDHandle)(*gdh)->gdNextGD;
  192.         }
  193.     }
  194.  
  195.     return false;
  196. }
  197.  
  198.  
  199. /**/
  200.  
  201.  
  202. Boolean CheckDirScrnWriteFor(WindowPtr win)
  203. {
  204.     return CanWriteDirectToScreen(win);
  205. }
  206.  
  207.  
  208. void NotMungeFunc(unsigned char *screenPtr, unsigned char *srcPtr)
  209. {
  210.     *screenPtr = ~*srcPtr;
  211. }
  212.  
  213.  
  214. /**/
  215.  
  216.  
  217. // Copy 8-bit pixels from "src" to the current port, no colour mapping....
  218. // CanWriteDirectToScreen() is assumed to have returned TRUE...
  219. void DirCopyPix(register long *srcPixels,
  220.                 unsigned long srcRB,
  221.                 int srcWid,
  222.                 register int srcHt,
  223.                 int winStartX, int winStartY,    // top/left of rect in window
  224.                 PixMungeFunc mungeFunc)
  225. {
  226.     Rect            dst;
  227.     unsigned long    dstRB;
  228.     register int    wid = srcWid;
  229.     register long    *macPtr = (long *)(gWinScreenPtr + (gMacRowBytes*winStartY) + winStartX);
  230.  
  231.     FailIf(wid & 0xF);        // || srcHt & 0x3)
  232.  
  233.     dst = gGlobalWinRect;
  234.     dst.top = gGlobalWinRect.top + winStartY;
  235.     dst.bottom = dst.top + srcHt;
  236.     dst.left = gGlobalWinRect.left + winStartX;
  237.     dst.right = dst.left + srcWid;
  238.     BeginDirectScreenWrite(&dst);
  239.  
  240.     srcRB /= sizeof(*srcPixels);    // we move longwords, so convert byte count to long count
  241.     wid /= sizeof(*srcPixels);        // ditto
  242.  
  243.                                     // pre-adjust the rowBytes values
  244.     dstRB = (gMacRowBytes / sizeof(*srcPixels)) - wid;
  245.     srcRB -= wid;
  246.  
  247.  
  248.     if (mungeFunc) {
  249.         srcWid = wid;                // keep tabs on this!
  250.         do {
  251.             wid = srcWid;
  252.             do {
  253.                 mungeFunc((unsigned char *)macPtr, (unsigned char *)srcPixels);
  254.                 mungeFunc(((unsigned char *)macPtr)+1, ((unsigned char *)srcPixels)+1);
  255.                 mungeFunc(((unsigned char *)macPtr)+2, ((unsigned char *)srcPixels)+2);
  256.                 mungeFunc(((unsigned char *)macPtr)+3, ((unsigned char *)srcPixels)+3);
  257.                 ++macPtr;
  258.                 ++srcPixels;
  259.             } while (--wid);
  260.             srcPixels += srcRB;
  261.             macPtr += dstRB;
  262.         } while (--srcHt);
  263.     }
  264.     else {                            // just a plain copy!
  265.         srcWid = wid >> 2;            // we move 4 longs per iteration
  266.         do {
  267.             wid = srcWid;
  268.             do {
  269.                 *macPtr++ = *srcPixels++;
  270.                 *macPtr++ = *srcPixels++;
  271.                 *macPtr++ = *srcPixels++;
  272.                 *macPtr++ = *srcPixels++;
  273.             } while (--wid);
  274.             srcPixels += srcRB;
  275.             macPtr += dstRB;
  276.         } while (--srcHt);
  277.     }
  278.  
  279.     EndDirectScreenWrite();
  280. }
  281.  
  282.  
  283. /**/
  284.  
  285. // Copy 8-bit pixels from "src" to the current port, no colour mapping....
  286. // CanWriteDirectToScreen() is assumed to have returned TRUE...
  287. // We scale every source pixel by 2 destination ones (handy for PC VGA
  288. // 320x200 => Mac 640x400...)
  289.  
  290. void DirCopyPixScaled2(long *paramSrcPixels,
  291.                 unsigned long srcRB,
  292.                 int srcWid,
  293.                 register int srcHt,
  294.                 int winStartX, int winStartY,    // top/left of rect in window
  295.                 PixMungeFunc mungeFunc)
  296. {
  297.     Rect                    dst;
  298.     register unsigned short    *macPtr;
  299.     register unsigned char    *srcPixels = (unsigned char *)paramSrcPixels;
  300.     unsigned long            dstRB;
  301.     register int            nextLine,
  302.                             wid = srcWid;
  303.  
  304.     FailIf(wid & 0xF);        // || srcHt & 0x3)
  305.  
  306.     macPtr = (unsigned short *)(gWinScreenPtr + (gMacRowBytes * winStartY) + winStartX);
  307.  
  308.     dst = gGlobalWinRect;
  309.     dst.top = gGlobalWinRect.top + winStartY;
  310.     dst.bottom = dst.top + (srcHt << 1);
  311.     dst.left = gGlobalWinRect.left + winStartX;
  312.     dst.right = dst.left + (srcWid << 1);
  313.     BeginDirectScreenWrite(&dst);
  314.  
  315.     // pre-adjust the rowBytes values
  316.  
  317.     dstRB = (gMacRowBytes * 2 / sizeof(*macPtr)) - wid;    // we do 2 lines at a time
  318.     srcRB -= wid;
  319.  
  320.     // Arrange "nextLine" so that "macPtr[nextLine]" is the pixel immediately below "macPtr"
  321.  
  322.     nextLine = gMacRowBytes / sizeof(*macPtr);
  323.  
  324.     if (mungeFunc) {
  325.         srcWid = wid;                // keep tabs on this!
  326.         do {
  327.             wid = srcWid;
  328.             do {
  329.                 mungeFunc((unsigned char *)macPtr, srcPixels);
  330.                 macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*(unsigned char *)macPtr];
  331.                 ++macPtr;
  332.                 ++srcPixels;
  333.             } while (--wid);
  334.             srcPixels += srcRB;
  335.             macPtr += dstRB;
  336.         } while (--srcHt);
  337.     }
  338.     else {                            // just a plain copy!
  339.         srcWid = wid >> 2;            // we do 4 pixels per loop iteration...
  340.         do {
  341.             wid = srcWid;
  342.             do {
  343.                 macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
  344.                 ++macPtr;
  345.                 ++srcPixels;
  346.                 macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
  347.                 ++macPtr;
  348.                 ++srcPixels;
  349.                 macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
  350.                 ++macPtr;
  351.                 ++srcPixels;
  352.                 macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
  353.                 ++macPtr;
  354.                 ++srcPixels;
  355.             } while (--wid);
  356.             srcPixels += srcRB;
  357.             macPtr += dstRB;
  358.         } while (--srcHt);
  359.     }
  360.  
  361.     EndDirectScreenWrite();
  362. }
  363.  
  364.  
  365. /**/
  366.  
  367.  
  368. void InitDirScrnGraphicsWindow(WindowPtr wp, InitPaletteFunc ipf)
  369. {
  370.     int            i, numColors = 256;
  371.     GDHandle    oldDev;
  372.     GrafPtr        rememberedPort;
  373.  
  374.     FailIfNot(gDirScrnInited);            // system must be initialised
  375.     FailIf(gDirScrnWindowInited);        // the particular window MUST NOT BE INITIALISED!
  376.     FailNil(wp);                        // window and initpal func cannot be nil
  377.     FailNil(ipf);
  378.  
  379.     gDirScrnWindowInited = true;
  380.  
  381.     // Remember the previous port & device...
  382.  
  383.     GetPort(&rememberedPort);
  384.     oldDev = GetGDevice();
  385.  
  386.     SetPort(wp);
  387.  
  388.     gDirClut = nil;
  389.  
  390.     // NB: •MUST• Have Explicit + Animated here...
  391.  
  392.     gDirPalette = NewPalette(numColors, nil, pmAnimated + pmExplicit + pmTolerant, kRGBTOLERANCE);
  393.     gDirClut = (CTabHandle)NewHandleClear(sizeof(ColorTable) - sizeof(ColorSpec));
  394.  
  395.     if (gDirClut && gDirPalette) {
  396.  
  397.         gPaletteColorsUsed = ipf(gDirPalette);
  398.         FailIf(gPaletteColorsUsed <= 0);
  399.  
  400.         Palette2CTab(gDirPalette, gDirClut);
  401.  
  402.         // Make sure each value field of the colortable is assigned to the
  403.         // corresponding entry in the palette and make sure the ctSeed field
  404.         // is given a unique value.
  405.  
  406.         for (i = 0; i < numColors; ++i)
  407.             (*gDirClut)->ctTable[i].value = i;
  408.  
  409.         i = GetCTSeed();
  410.         (*gDirClut)->ctSeed = i;
  411.  
  412.         // Setting bit 14 of the “ctFlags” field tells the color table to refer
  413.         // to the palette indexes instead of its rgb values.  This is necessary
  414.         // since we (might) perform animation by altering the palette.
  415.  
  416.         (*gDirClut)->ctFlags |= (0x8000|0x4000);
  417.  
  418.         // Associate the new palette with our window.
  419.  
  420.         SetPalette(wp, gDirPalette, /*pmUpdates:*/ true);
  421.  
  422.         AnimatePalette(wp, gDirClut, 0, 0, (*gDirClut)->ctSize+1);
  423.     }
  424.  
  425.     // Restore the original port.
  426.  
  427.     SetGDevice(oldDev);
  428.     SetPort(rememberedPort);
  429. }
  430.  
  431.  
  432. /**/
  433.  
  434.  
  435. void TermDirScrnGraphicsWindow(WindowPtr wp)
  436. {
  437.     FailIfNot(gDirScrnInited);
  438.     FailIfNot(gDirScrnWindowInited);
  439.     FailNil(gDirClut);
  440.     FailNil(gDirPalette);
  441.  
  442.     DisposeCTable(gDirClut);
  443.     gDirClut = 0;
  444.  
  445.     DisposePalette(gDirPalette);
  446.     gDirPalette = 0;
  447.  
  448.     gDirScrnWindowInited = false;
  449. }
  450.  
  451.  
  452. /**/
  453.  
  454.  
  455. void InitDirScrnWrite(void)        // initialise the system
  456. {
  457.     int    i, j;
  458.  
  459.     FailIf(gDirScrnInited);        // cannot already be initialised
  460.  
  461.     // Create a couple of empty regions...
  462.  
  463.     gPreviousVisRgn = NewRgn();
  464.     gBoundRgn = NewRgn();
  465.  
  466.     // Fixup the replicated byte ==> longword lut...
  467.  
  468.     ReplicatedByteLUT = (long *)NewPtr(256 * sizeof(long));
  469.     FailNil(ReplicatedByteLUT);
  470.  
  471.     for (i = 0; i < 256; ++i) {
  472.         char *p = (char *)(ReplicatedByteLUT + i);
  473.         for (j = 0; j < sizeof(long); ++j)
  474.             p[j] = i;
  475.     }
  476.  
  477.     gDirScrnInited = true;
  478. }
  479.  
  480.  
  481.